package il.technion.cs236369.database;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * The cache class. Implements SQL database actions.
 * @author itamar talmi 0396055979 itamar.talmi@gmail.com , ofir haviv 300228921 havivi1986@gmail.com
 *
 */
public class Cache implements ICache {
	
	private final String tableName;
	private final String[] columns = { "url", "headers", "body", "etag" };
	
	private Connection connection;
	
	/**
	 * The constructor of the Cache class.
	 * @param driverName - The driver name of the sql.
	 * @param databaseUrl - The url of the sql.
	 * @param dbName - The name of the sql database.
	 * @param tableName - The name of the cache table.
	 * @param userName - The user name of the table.
	 * @param password - The password of the table.
	 * @throws ClassNotFoundException - If any error accure.
	 * @throws SQLException - If any error accure.
	 */
	public Cache(String driverName, String databaseUrl, String dbName, String tableName, String userName, String password) throws ClassNotFoundException, SQLException{
		Class.forName(driverName);
		connection = DriverManager.getConnection(databaseUrl + dbName, userName, password);
		this.tableName = tableName;
	}

	@Override
	public void storeData(HttpMessageCacheDetails httpMessage) {
		if (GetData(httpMessage.url) != null){
			updateData(httpMessage);
			return;
		}
		
		PreparedStatement statement = null;
		try {
			statement = connection.prepareStatement("INSERT INTO " + tableName + " VALUES(?, ?, ?, ?)");
			statement.setString(1, httpMessage.url);
			statement.setString(2, httpMessage.headers);
			statement.setBytes(3, httpMessage.body);
			statement.setString(4, httpMessage.etag);
			statement.execute();
			//System.out.println("Message Added!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
			
		} catch (SQLException e) {
			//e.printStackTrace();
		}
		finally{
			try { if (statement != null) statement.close();} catch (SQLException e) {}
		}
	}
	
	private void updateData(HttpMessageCacheDetails httpMessage){
		PreparedStatement statement = null;
		try {
			statement = connection.prepareStatement("update " + tableName + " set " +
				columns[1] + "=?, " +
				columns[2] + "=?, " + 
				columns[3] + "=? " + 
				"where " + columns[0] + "=?");
			
			statement.setString(1, httpMessage.headers);
			statement.setBytes(2, httpMessage.body);
			statement.setString(3, httpMessage.etag);
			statement.setString(4, httpMessage.url);
			statement.execute();
			statement.close();
			//System.out.println("Message Updates!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
			
		} catch (SQLException e) {
			//e.printStackTrace();
		}
		finally{
			try { if (statement != null) statement.close();} catch (SQLException e) {}
		}
	}

	@Override
	public HttpMessageCacheDetails GetData(String url) {
		PreparedStatement statement;
		try {
			statement = connection.prepareStatement("select * from " + tableName + " where " + columns[0] + "=?");
		} catch (SQLException e1) {
			//e1.printStackTrace();
			return null;
		}
		ResultSet rs = null;
		try {
			statement.setString(1, url);
			rs = statement.executeQuery();
			if (rs.next() == false)
				return null;
			//System.out.println("Message Retrived!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
			return new HttpMessageCacheDetails(
					rs.getString(columns[0]),
					rs.getString(columns[1]),
					rs.getBytes(columns[2]),
					rs.getString(columns[3]));
			
			
		} catch (SQLException e) {
			//e.printStackTrace();
			return null;
		}
		finally{
			try {statement.close();} catch (Exception e) {}
			try {if (rs != null) rs.close();} catch (Exception e) {}
		}
	}

	@Override
	public void deleteData(String url) {
		PreparedStatement statement = null;
		try {
			statement = connection.prepareStatement("DELETE FROM " + tableName + " WHERE " + columns[0] + "=?");
			statement.setString(1, url);
			statement.execute();
			
		} catch (SQLException e) {
			//e.printStackTrace();
		} finally{
			try { if (statement != null) statement.close();} catch (SQLException e) {}
		}
		
	}

}
